package com.nulldev.util.networking.async2.udp.connectors.packets;

import java.net.DatagramPacket;

import com.nulldev.util.networking.async2.events.ManualResetEvent;
import com.nulldev.util.networking.async2.udp.connectors.UDPConnector;

public class OutgoingUDPClientPacket implements Runnable {

	public ManualResetEvent fDone = new ManualResetEvent(false);
	private UDPConnector fConnector;
	private DatagramPacket fData;
	private OutgoingUDPClientPacket fPreviousPacket;
	public boolean fCancel = false;

	/**
	 * Constructs a new outgoing packet for an existing UDP Connector. Use this
	 * class to send data from the UDP Connector to a server. This is an outgoing
	 * message that will remain in the clients thread pool as a job for the thread
	 * pool workers.
	 * 
	 * @param connector      is the UDPConnector where this message belongs to.
	 * @param data           is the outgoing DatagramPacket.
	 * @param previousPacket is the previous outgoing packet of the UDPConnector.
	 */
	public OutgoingUDPClientPacket(UDPConnector connector, DatagramPacket data, OutgoingUDPClientPacket previousPacket) {
		fConnector = connector;
		fData = data;
		fPreviousPacket = previousPacket;

		connector.getUDPClient().getMyThreadPool().execute(this);
	}

	/**
	 * Cancel this outgoing packet. By calling this method this and all the previous
	 * outgoing packets that are stored in the thread pool will be canceled. Call
	 * this method for the last outgoing packet of the UDPConnector when the
	 * UDPConnector disconnects.
	 */
	public void cancel() {
		fCancel = true;
		fDone.set();
	}

	@Override
	public void run() {
		try {
			if (fPreviousPacket == null) {
				fConnector.fSocket.send(fData);
				fConnector.fBytesOut += fData.getLength();
			} else {
				fPreviousPacket.fDone.waitOne();
				if (!fCancel && !fPreviousPacket.fCancel) {
					fConnector.fSocket.send(fData);
					fConnector.fBytesOut += fData.getLength();
				} else {
					fCancel = true;
				}
			}
		} catch (Exception ex) {
		}

		if (fPreviousPacket != null) {
			fPreviousPacket = null;
		}

		fDone.set();
	}

	/**
	 * Returns the DatagramPacket of this outgoing UDP packet.
	 * 
	 * @return the DatagramPacket of this outgoing UDP packet.
	 */
	public DatagramPacket getData() {
		return fData;
	}

	/**
	 * Returns the previus outgoing packet of the client. If the packet is null
	 * means that the packet has been send to server.
	 * 
	 * @return the previus outgoing packet of the client.
	 */
	public OutgoingUDPClientPacket getPreviousPacket() {
		return fPreviousPacket;
	}
}
